package vip.yyzhu.redisadmin.api.key.controller;

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import jdk.nashorn.internal.ir.IfNode;
import lombok.val;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import redis.clients.jedis.ScanParams;
import redis.clients.jedis.ScanResult;
import vip.yyzhu.redisadmin.aop.permissions.AuthUnique;
import vip.yyzhu.redisadmin.aop.verifyKeyType.VerifyKeyType;
import vip.yyzhu.redisadmin.api.pub.jopo.RedisHash;
import vip.yyzhu.redisadmin.api.pub.jopo.RedisZset;
import vip.yyzhu.redisadmin.jopo.ResData;
import vip.yyzhu.redisadmin.jopo.ResJson;
import vip.yyzhu.redisadmin.redis.RedisList;
import vip.yyzhu.redisadmin.util.Tool;

import javax.servlet.http.HttpServletRequest;
import java.util.*;

@RestController
@RequestMapping(value = "/api/key/hash", produces = "application/json;charset=UTF-8")
@SuppressWarnings("all")
public class HashController {
    @Autowired
    RedisList redisList;
    @Autowired
    Tool tool;
    ObjectMapper mapper = new ObjectMapper();


    @VerifyKeyType(value = "hash", empty = true)
    @RequestMapping(value = "/hset", method = RequestMethod.POST)
    public Object lset(HttpServletRequest request,
                       @RequestParam String key,
                       @RequestParam(required = false, defaultValue = "true") boolean cover,
                       @RequestParam String adds) throws Exception {
        val jedis = Tool.getJedis(request, redisList);
        // json转liat
        List<RedisHash> list = mapper.readValue(adds, new TypeReference<List<RedisHash>>() {
        });
        // 需要添加的map
        Map<String, String> success = new HashMap<>();
        // 已经存在的
        Map<String, String> repeat = new HashMap<>();

        for (RedisHash hash : list) {
            if (cover || !jedis.hexists(key, hash.getField())) { // 开启覆盖 或者 key不存在
                success.put(hash.getField(), hash.getValue());
                jedis.hset(key, hash.getField(), hash.getValue());
            } else { // 跳过已存在的
                repeat.put(hash.getField(), hash.getValue());
            }
        }

        Map map = new HashMap();
        map.put("key", key);
        map.put("repeat", repeat);
        map.put("success", success);
        ResData res = new ResData(map);
        return new ResJson(200, "成功", res);
    }


    @VerifyKeyType(value = "hash", empty = true)
    @RequestMapping(value = "/hget", method = RequestMethod.POST)
    public Object hget(HttpServletRequest request,
                       @RequestParam String key,
                       @RequestParam String field) throws Exception {
        val jedis = Tool.getJedis(request, redisList);

        String hget = jedis.hget(key, field);

        Map map = new HashMap();
        map.put("value", hget);
        map.put("key", key);
        ResData res = new ResData();
        res.setMap(map);
        return new ResJson(200, "成功", res);
    }

    /**
     * 使用游标获取kes列表
     *
     * @param cursor 游标
     * @param size   一页的数量
     * @param match  模糊搜索
     * @return {"map":{"total":10, "sift":5, "cursor":"0"}, "list":[]}
     */
    @AuthUnique
    @RequestMapping(value = "/hscan", method = RequestMethod.POST)
    public Object hscan(HttpServletRequest request,
                        @RequestParam String key,
                        @RequestParam String cursor,
                        @RequestParam(required = false, defaultValue = "100") int size,
                        @RequestParam(required = false, defaultValue = "100") int page_size,
                        @RequestParam(required = false) String match) {
        val jedis = tool.getJedis(request);

        ScanParams scanParams = new ScanParams();
        scanParams.count(page_size < 200 ? 200 : page_size);//页数
        if (match != null && !match.equals("") && !match.equals("**")) {
            scanParams.match(match);
        }

        String new_cursor = cursor;
        Map data = new HashMap();
        System.out.println("key = " + key);
        //  加载到size的数量
        while (data.size() < size) {
            ScanResult<Map.Entry<String, String>> hscan = jedis.hscan(key, new_cursor, scanParams);
            new_cursor = hscan.getStringCursor();
            for (Map.Entry<String, String> entry : hscan.getResult()) {
                data.put(entry.getKey(), entry.getValue());
            }
            if (new_cursor.equals("0")) {
                break;
            }
        }
        Map map = new HashMap();
        map.put("total", jedis.hlen(key));
        map.put("cursor", new_cursor);
        ResData res = new ResData();
        res.setList(data);
        res.setMap(map);
        return new ResJson(200, "成功", res);
    }


    @VerifyKeyType("hash")
    @RequestMapping(value = "/hdel", method = RequestMethod.POST)
    public Object hdel(HttpServletRequest request,
                       @RequestParam String key,
                       @RequestParam String field) throws Exception {
        val jedis = tool.getJedis(request);
        if (!jedis.hexists(key, field)) {
            return new ResJson(200, "成功", new ResData("key已经被删除，请刷新后重试"));
        }
        Long hdel = jedis.hdel(key, field);
        Map map = new HashMap();
        map.put("key", key);
        map.put("fields", field);
        ResData res = new ResData(map);
        res.setRedis(hdel);
        return new ResJson(200, "成功", res);
    }


    @VerifyKeyType(value = "hash", empty = true)
    @RequestMapping(value = "/hedit", method = RequestMethod.POST)
    public Object hedit(HttpServletRequest request,
                        @RequestParam String key,
                        @RequestParam String field,
                        @RequestParam String oldValue,
                        @RequestParam String value) throws Exception {
        val jedis = Tool.getJedis(request, redisList);
        if (!oldValue.equals(jedis.hget(key, field))) {
            return new ResJson(4000, "修改失败", new ResData("数据可能已经被改变，请刷新后重新发起修改操作"));
        }
        jedis.hset(key, field, value);

        Map map = new HashMap();
        map.put("key", key);
        map.put("value", value);
        map.put("oldValue", oldValue);
        ResData res = new ResData(map);
        return new ResJson(200, "成功", res);
    }
}
